﻿using Admin.Service.UserInfos.DTO;
using BLL.UserInfos.DTO;
using Admin.Repository.Userinfos;
using System;
using System.Collections.Generic;
using System.Linq;
using Admin.UserInfos;
using Admin.UserRoles;
using Admin.Repository.Roles;
using Admin.Repository.UserRoles;
using Microsoft.Extensions.Configuration;
using System.IO;
using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Hosting;
using AutoMapper;
using NLog;
using Microsoft.Extensions.Logging;

namespace BLL.UserInfos
{
    public class UserInfoService : IUserInfoService
    {
        private readonly IUserinfoRepository userinfoDal;
        private readonly IRoleRepository roleRepository;
        private readonly IUserRoleRepository userRoleRepository;
        private readonly IConfiguration configuration;
        private readonly IWebHostEnvironment environment;
        private readonly IMapper mapper;
        private readonly ILogger<UserInfoService> logger;

        public UserInfoService(IUserinfoRepository userinfoDal, IRoleRepository roleRepository, IUserRoleRepository userRoleRepository, IConfiguration configuration, IWebHostEnvironment environment, IMapper mapper, ILogger<UserInfoService> logger)
        {
            this.userinfoDal = userinfoDal;
            this.roleRepository = roleRepository;
            this.userRoleRepository = userRoleRepository;
            this.configuration = configuration;
            this.environment = environment;
            this.mapper = mapper;
            this.logger = logger;
        }

        /// <summary>
        /// 删除 单删
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int Delete(int id)
        {
            try
            {
                //删除文件
                //根据id查找文件
                var user = userinfoDal.QueryId(id);
                //文件所在路径
                //environment.WebRootPath根目录
                var path = $"{environment.WebRootPath}{user.UserInfoPic}";

                if (File.Exists(path))
                {
                    File.Delete(path);
                }

                //日志信息
                logger.LogInformation($"删除了用户{id}的信息");

                return userinfoDal.Delete(id);
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                return 0;
            }
        }

        /// <summary>
        /// 删除 批删 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public int DeleteList(int[] ids)
        {
            //删除文件
            var user = userinfoDal.QueryList(m => ids.Contains(m.UserInfoId));

            foreach (var item in user)
            {
                var path = $"{environment.WebRootPath}{user}";

                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                return userinfoDal.Delete(ids);
            }


            return userinfoDal.Delete(ids);
        }

        /// <summary>
        /// 显示用户信息
        /// </summary>
        /// <param name="username"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <returns></returns>
        public PageRestFullDto<ShowDto> Queryable(int page, int size, string username, DateTime? starttime, DateTime? endtime)
        {
            //返回Dto
            var like = userRoleRepository.Queryable().Join(userinfoDal.Queryable(), a => a.UserInfoId, b => b.UserInfoId, (a, b) => new
            {
                a.RoleId,
                a.UserRoleId,
                b.UserInfoId,
                b.UserInfoPic,
                b.UserName,
                b.UserPassword,
                b.Name,
                b.UserPhone,
                b.Email,
                b.CreateTime,
            }).Join(roleRepository.Queryable(), a => a.RoleId, c => c.RoleId, (a, c) => new
            {
                c.RoleName,
                a.UserRoleId,
                a.RoleId,
                a.UserInfoId,
                a.UserInfoPic,
                a.UserName,
                a.UserPassword,
                a.Name,
                a.UserPhone,
                a.Email,
                a.CreateTime,
            }).Select(a => new ShowDto
            {
                UserRoleId = a.UserRoleId,
                RoleName = a.RoleName,
                UserInfoId = a.UserInfoId,
                UserInfoPic = a.UserInfoPic,
                UserName = a.UserName,
                UserPassword = a.UserPassword,
                Name = a.Name,
                UserPhone = a.UserPhone,
                Email = a.Email,
                CreateTime = a.CreateTime,
            }).ToList();

            //判断
            if (!string.IsNullOrEmpty(username))
            {
                like = like.Where(x => x.UserName.Contains(username)).ToList();
            }
            if (starttime != null)
            {
                like = like.Where(x => x.CreateTime >= starttime).ToList();
            }
            if (endtime != null)
            {
                like = like.Where(x => x.CreateTime <= endtime).ToList();
            }

            //分页
            var data = like.Skip((page - 1) * size).Take(size).ToList();

            //总条数
            int totalCount = like.Count;

            return new PageRestFullDto<ShowDto> { Data = data, TotalCount = totalCount };
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public RestFullDto AddUserInfo(AddUserInfoDto addUserInfoDto)
        {
            try
            {
                //判断用户名是否重复
                var list = userinfoDal.GetUserName(addUserInfoDto.UserName);

                //判断确认密码是否与密码一致
                if (addUserInfoDto.UserPassword == addUserInfoDto.ConfirmPassword)
                {
                    if (list == null)
                    {
                        var entity = mapper.Map<UserInfo>(addUserInfoDto);

                        entity.UserPassword = MD5Help.MD5Hash(addUserInfoDto.UserPassword);

                        entity.UserRoles = addUserInfoDto.RoleId.Select(m => new UserRole
                        {
                            RoleId = m
                        }).ToList();

                        var user = userinfoDal.Create(entity);

                        //var user = userinfoDal.Create(new UserInfo
                        //{
                        //    UserInfoPic = addUserInfoDto.UserInfoPic,
                        //    UserName = addUserInfoDto.UserName,
                        //    UserPassword = MD5Help.MD5Hash(addUserInfoDto.UserPassword),
                        //    UserPhone = addUserInfoDto.UserPhone,
                        //    Name = addUserInfoDto.Name,
                        //    Email = addUserInfoDto.Email,
                        //    UserRoles = addUserInfoDto.RoleId.Select(m => new UserRole
                        //    {
                        //        RoleId = m
                        //    }).ToList()
                        //});

                        //循环
                        //foreach (var item in addUserInfoDto.RoleId)
                        //{
                        //    userRoleRepository.Create(new UserRole
                        //    {
                        //        UserInfoId = user.UserInfoId,
                        //        RoleId = item,                            
                        //    });
                        //}

                        logger.LogInformation($"注册了用户{addUserInfoDto.Name}的信息");

                        return new RestFullDto { Code = 1, Message = "恭喜您，注册成功！" };
                    }
                    else
                    {
                        return new RestFullDto { Code = 2, Message = "用户名/手机号/邮箱已存在，请重新输入！" };
                    }
                }
                else
                {
                    return new RestFullDto { Code = 3, Message = "确认密码与密码不一致，请重新输入！" };
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                return new RestFullDto { Code = 0 };
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public RestFullDto UpdUserInfo(AddUserInfoDto addUserInfoDto)
        {
            try
            {
                if (!userinfoDal.Queryable().Any(m => m.UserName == addUserInfoDto.UserName && m.UserInfoId != addUserInfoDto.UserInfoId))
                {
                    //删除中间表
                    userRoleRepository.Delete(m => m.UserInfoId == addUserInfoDto.UserInfoId);

                    //重新添加中间表
                    //var user = userinfoDal.Update(new UserInfo
                    //{
                    //    UserInfoId = addUserInfoDto.UserInfoId,
                    //    UserInfoPic = addUserInfoDto.UserInfoPic,
                    //    UserName = addUserInfoDto.UserName,
                    //    UserPassword = MD5Help.MD5Hash(addUserInfoDto.UserPassword),
                    //    UserPhone = addUserInfoDto.UserPhone,
                    //    Name = addUserInfoDto.Name,
                    //    Email = addUserInfoDto.Email,
                    //    UserRoles = addUserInfoDto.RoleId.Select(m => new UserRole
                    //    {
                    //        RoleId = m
                    //    }).ToList()
                    //});

                    var entity = mapper.Map<UserInfo>(addUserInfoDto);
                    entity.UserRoles = addUserInfoDto.RoleId.Select(m => new UserRole
                    {
                        RoleId = m
                    }).ToList();

                    userinfoDal.Update(entity);

                    //日志信息
                    logger.LogInformation($"修改了用户{addUserInfoDto.Name}的信息");

                    return new RestFullDto { Code = 1, Message = "恭喜您，修改成功！" };
                }
                else
                {
                    return new RestFullDto { Code = 2, Message = "用户名/手机号/邮箱已存在，请重新输入！" };
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                throw;
            }

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        public RestDto<UserInfoDto> GetLogin(LoginDto loginDto)
        {
            //判断用户名是否重复
            var list = userinfoDal.GetUserName(loginDto.UserName);

            if (list == null)
            {
                return new RestDto<UserInfoDto> { Code = 1, Message = "该用户名/手机号/邮箱不存在，请重新输入！" };
            }
            else
            {
                if (MD5Help.MD5Hash(loginDto.UserPassword) == list.UserPassword)
                {
                    //写Session或Cookies换成JWT
                    List<Claim> claims = new List<Claim> {
                        new Claim(JwtClaimTypes.Id,list.UserInfoId.ToString()),
                        new Claim(JwtClaimTypes.Name,list.UserName),
                        new Claim(ClaimTypes.Name,list.UserName),
                    };

                    //获取当前用户的角色信息
                    userRoleRepository.QueryList(m => m.UserInfoId == list.UserInfoId).ToList().ForEach(m =>
                    {
                        claims.Add(new Claim(ClaimTypes.Role, m.RoleId.ToString()));
                    });

                    //JWT密钥
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:key"]));

                    //算法
                    var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    //过期时间
                    DateTime expires = DateTime.UtcNow.AddHours(10);


                    //Payload负载
                    var token = new JwtSecurityToken(
                        issuer: configuration["JwtConfig:Issuer"],
                        audience: configuration["JwtConfig:Audience"],
                        claims: claims,
                        notBefore: DateTime.UtcNow,
                        expires: expires,
                        signingCredentials: cred
                        );

                    var handler = new JwtSecurityTokenHandler();

                    //生成令牌
                    string jwt = handler.WriteToken(token);

                    return new RestDto<UserInfoDto>
                    {
                        Code = 2,
                        Message = "恭喜您，登陆成功！",
                        Data = new UserInfoDto
                        {
                            UserName = list.UserName,
                            UserPassword = list.UserPassword,
                            Token = jwt
                        }
                    };
                }
                else
                {
                    return new RestDto<UserInfoDto> { Code = 3, Message = "密码错误，请重新输入！" };
                }
            }
        }
    }
}
